package bank.gui;

import java.awt.event.ActionEvent;
import java.util.Map;
import java.util.Vector;

import bank.Model;
import bank.factory.AccountFactory;
import framework.BaseManager;
import framework.account.IAccount;
import framework.command.ICommand;
import framework.command.impl.AddInterestCommand;
import framework.customer.ICustomer;
import framework.factory.CustomerFactory;

import javax.swing.*;

/**
 * @author Elbek Kamoliddinov
 */
public class Controller {
    /**
     * @uml.property name="view"
     * @uml.associationEnd multiplicity="(1 1)"
     */
    View view;

    /**
     * @uml.property name="bank"
     * @uml.associationEnd multiplicity="(1 1)"
     */

    public Controller(View view) {

        this.view = view;
        view.addListener(new SymAction());
        view.addListenerToWindow(new SymWindow());
    }

    class SymWindow extends java.awt.event.WindowAdapter {
        public void windowClosing(java.awt.event.WindowEvent event) {
            Object object = event.getSource();
            if (object == view)
                BankFrm_windowClosing(event);
        }
    }

    class SymAction implements java.awt.event.ActionListener {
        public void actionPerformed(java.awt.event.ActionEvent event) {
            Object object = event.getSource();
            if (object == view.JButton_Exit)
                JButtonExit_actionPerformed(event);
            else if (object == view.JButton_PerAC)
                JButtonPerAC_actionPerformed(event);
            else if (object == view.JButton_CompAC)
                JButtonCompAC_actionPerformed(event);
            else if (object == view.JButton_Deposit)
                JButtonDeposit_actionPerformed(event);
            else if (object == view.JButton_Withdraw)
                JButtonWithdraw_actionPerformed(event);
            else if (object == view.JButton_Addinterest)
                JButtonAddinterest_actionPerformed(event);
            else if (object == view.JButton_Report)
                JButton_Report_actionPerformed(event);
        }
    }

    void JButton_Report_actionPerformed(ActionEvent event) {
        // get selected name
        int selection = view.JTable1.getSelectionModel().getMinSelectionIndex();
        if (selection == -1)
            return;
        IAccount account = Model.getInstance().getSelectedAccount(selection);
        Map<String, String> report = Model.getInstance().getAccountData(account.getAccountNo());
        JDialogGenBill genBill = new JDialogGenBill(view, report);
        genBill.show();
    }

    void BankFrm_windowClosing(java.awt.event.WindowEvent event) {
        BankFrm_windowClosing_Interaction1(event);
    }

    void BankFrm_windowClosing_Interaction1(java.awt.event.WindowEvent event) {
        try {
            this.exitApplication();
        } catch (Exception e) {
        }
    }

    void exitApplication() {
        try {
            view.setVisible(false); // hide the Frame
            view.dispose(); // free the system resources
            System.exit(0); // close the application
        } catch (Exception e) {
        }
    }

    void JButtonDeposit_actionPerformed(java.awt.event.ActionEvent event) {
        // get selected name
        int selection = view.JTable1.getSelectionModel().getMinSelectionIndex();
        if (selection == -1)
            return;
        view.setSelection(selection);
        IAccount account = Model.getInstance().getSelectedAccount(selection);
        JDialog_Deposit depositDialog = new JDialog_Deposit(view, account);
        depositDialog.setBounds(450, 20, 300, 380);
        depositDialog.show();
        Model.getInstance().refreshRows();
    }

    void JButtonWithdraw_actionPerformed(java.awt.event.ActionEvent event) {
        // get selected name
        int selection = view.JTable1.getSelectionModel().getMinSelectionIndex();
        if (selection == -1)
            return;
        view.setSelection(selection);
        IAccount account = Model.getInstance().getSelectedAccount(selection);
        JDialog_Withdraw withdrawDialog = new JDialog_Withdraw(view, account);
        withdrawDialog.setBounds(450, 20, 300, 380);
        withdrawDialog.show();
        Model.getInstance().refreshRows();
    }

    void JButtonAddinterest_actionPerformed(java.awt.event.ActionEvent event) {

        ICommand command = new AddInterestCommand(Model.getInstance().getAccounts());
        BaseManager.getInstance().execute(command);

        for (int i = 0; i < view.getModel().getRowCount(); i++) {
            String accNumber = view.getModel().getValueAt(i, 0).toString();
            view.getModel().setValueAt(Model.getInstance().getAccount(accNumber).getBalance(), i, 5);
        }
        Model.getInstance().refreshRows();
    }

    // When the Exit button is pressed this code gets executed
    // this will exit from the system
    void JButtonExit_actionPerformed(java.awt.event.ActionEvent event) {
        System.exit(0);
    }

    @SuppressWarnings("deprecation")
    void JButtonPerAC_actionPerformed(java.awt.event.ActionEvent event) {

        /*
           * JDialog_AddPAcc type object is for adding personal information
           * construct a JDialog_AddPAcc type object set the boundaries and show
           * it
           */

        JDialog_AddPAcc pac = new JDialog_AddPAcc(view);
        pac.setBounds(450, 20, 300, 330);
        pac.show();

        if (!pac.isCreated())
            return;

        Map<String, String> cusMap = pac.getCustomerMap();

        ICustomer customer = AddAndGetCustomer(cusMap);
        IAccount acc = AccountFactory.createAccount(cusMap.get("type"), cusMap.get("ccNumber"));
        customer.addAccount(acc);
        cusMap.put("amount", String.valueOf(acc.getBalance()));
        cusMap.put("ch/s", acc.getType());

        view.getModel().addRow(map2row(cusMap));
        Model.getInstance().addRow(cusMap);
        view.JTable1.getSelectionModel().setAnchorSelectionIndex(-1);
    }

    @SuppressWarnings("deprecation")
    void JButtonCompAC_actionPerformed(java.awt.event.ActionEvent event) {

        /*
           * construct a JDialog_AddCompAcc type object set the boundaries and
           * show it
           */

        JDialog_AddCompAcc pac = new JDialog_AddCompAcc(view);
        pac.setBounds(450, 20, 300, 330);
        pac.setVisible(true);
        if (!pac.isCreated())
            return;

        Map<String, String> cusMap = pac.getCustomerMap();

        ICustomer customer = AddAndGetCustomer(cusMap);
        IAccount acc = AccountFactory.createAccount(cusMap.get("type"), cusMap.get("ccNumber"));
        customer.addAccount(acc);
        cusMap.put("amount", String.valueOf(acc.getBalance()));
        cusMap.put("ch/s", acc.getType());
        view.getModel().addRow(map2row(cusMap));
        Model.getInstance().addRow(cusMap);
        view.JTable1.getSelectionModel().setAnchorSelectionIndex(-1);
    }

    private Vector<String> map2row(Map<String, String> cusMap) {
        Vector<String> row = new Vector<String>();
        row.add(cusMap.get("ccNumber"));
        row.add(cusMap.get("name"));
        row.add(cusMap.get("city"));
        row.add(cusMap.get("p/c"));
        row.add(cusMap.get("ch/s"));
        row.add(cusMap.get("amount"));
        return row;
    }

    private ICustomer AddAndGetCustomer(Map<String, String> map) {
        if (!Model.getInstance().isExist(map.get("name"))) {
            ICustomer customer = CustomerFactory.createCustomer(getArrayMap(map));
            Model.getInstance().addCustomer(customer);
            return customer;
        } else
            return Model.getInstance().getCustomerByName(map.get("name"));
    }

    private Object[] getArrayMap(Map<String, String> map) {
        Object[] tmp = new Object[8];

        tmp[0] = map.get("p/c");
        tmp[1] = map.get("name");
        tmp[2] = map.get("street");
        tmp[3] = map.get("city");
        tmp[4] = map.get("zip");
        tmp[5] = map.get("email");
        tmp[6] = map.get("state");

        if (map.containsKey("numOfEmp"))
            tmp[7] = map.get("numOfEmp");
        else
            tmp[7] = map.get("dob");
        return tmp;
    }
}